From c3c33ac1686403bcb6ecd32798bea126764438e9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 20 Apr 2019 04:32:29 +0000 Subject: [PATCH] entry completion: Use a popover This lets us remove a use of GTK_WINDOW_POPUP, which should eventually be going away. We need to disable treeview search, since it creates a toplevel that will disrupt our grabbing popup, causing it to be dismissed. We don't need to grab ourselves, since the popover code does it for us. We don't need to reposition our window, since the popover takes care of that too. --- gtk/gtkentrycompletion.c | 129 ++++++++------------------------------- 1 file changed, 24 insertions(+), 105 deletions(-) diff --git a/gtk/gtkentrycompletion.c b/gtk/gtkentrycompletion.c index fb6cb1709f..068a6b271c 100644 --- a/gtk/gtkentrycompletion.c +++ b/gtk/gtkentrycompletion.c @@ -79,8 +79,7 @@ #include "gtkscrolledwindow.h" #include "gtksizerequest.h" #include "gtkbox.h" -#include "gtkwindow.h" -#include "gtkwindowgroup.h" +#include "gtkpopover.h" #include "gtkentry.h" #include "gtkmain.h" #include "gtkmarshalers.h" @@ -526,6 +525,7 @@ gtk_entry_completion_constructed (GObject *object) G_CALLBACK (gtk_entry_completion_list_activated), completion); + gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->tree_view), FALSE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE); gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->tree_view), TRUE); gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW (priv->tree_view), TRUE); @@ -561,6 +561,7 @@ gtk_entry_completion_constructed (GObject *object) g_signal_connect (priv->action_view, "row-activated", G_CALLBACK (gtk_entry_completion_action_activated), completion); + gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->action_view), FALSE); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->action_view), FALSE); gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (priv->action_view), TRUE); gtk_tree_view_set_activate_on_single_click (GTK_TREE_VIEW (priv->action_view), TRUE); @@ -578,9 +579,8 @@ gtk_entry_completion_constructed (GObject *object) NULL); /* pack it all */ - priv->popup_window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_window_set_resizable (GTK_WINDOW (priv->popup_window), FALSE); - gtk_window_set_type_hint (GTK_WINDOW(priv->popup_window), GDK_SURFACE_TYPE_HINT_COMBO); + priv->popup_window = gtk_popover_new (NULL); + gtk_popover_set_position (GTK_POPOVER (priv->popup_window), GTK_POS_BOTTOM); controller = gtk_event_controller_key_new (); g_signal_connect (controller, "key-pressed", @@ -762,38 +762,12 @@ gtk_entry_completion_dispose (GObject *object) GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (object); GtkEntryCompletionPrivate *priv = completion->priv; - if (priv->tree_view) - { - gtk_widget_destroy (priv->tree_view); - priv->tree_view = NULL; - } - if (priv->entry) gtk_entry_set_completion (GTK_ENTRY (priv->entry), NULL); - if (priv->actions) - { - g_object_unref (priv->actions); - priv->actions = NULL; - } - - if (priv->action_view) - { - g_object_unref (priv->action_view); - priv->action_view = NULL; - } - - if (priv->popup_window) - { - gtk_widget_destroy (priv->popup_window); - priv->popup_window = NULL; - } - - if (priv->cell_area) - { - g_object_unref (priv->cell_area); - priv->cell_area = NULL; - } + g_clear_object (&priv->actions); + g_clear_object (&priv->action_view); + g_clear_object (&priv->cell_area); G_OBJECT_CLASS (gtk_entry_completion_parent_class)->dispose (object); } @@ -1461,39 +1435,11 @@ _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion) NULL, FALSE, 0.0, 0.0); gtk_tree_path_free (path); } - - if (gtk_window_get_transient_for (GTK_WINDOW (completion->priv->popup_window))) - { - gdk_surface_move_to_rect (_gtk_widget_get_surface (completion->priv->popup_window), - &allocation, - GDK_GRAVITY_SOUTH, - GDK_GRAVITY_NORTH, - GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE_X, - 0, 0); - gtk_widget_show (completion->priv->popup_window); - } -} - -static void -prepare_popup_func (GdkSeat *seat, - GdkSurface *surface, - gpointer user_data) -{ - GtkEntryCompletion *completion = user_data; - - /* prevent the first row being focused */ - gtk_widget_grab_focus (completion->priv->tree_view); - - gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view))); - gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view))); - - gtk_widget_show (completion->priv->popup_window); } static void gtk_entry_completion_popup (GtkEntryCompletion *completion) { - GtkWidget *toplevel; GtkText *text = gtk_entry_get_text_widget (GTK_ENTRY (completion->priv->entry)); if (gtk_widget_get_mapped (completion->priv->popup_window)) @@ -1505,40 +1451,14 @@ gtk_entry_completion_popup (GtkEntryCompletion *completion) if (!gtk_widget_has_focus (GTK_WIDGET (text))) return; - if (completion->priv->has_grab) - return; - - gtk_widget_show (completion->priv->vbox); - /* default on no match */ completion->priv->current_selected = -1; - toplevel = gtk_widget_get_toplevel (completion->priv->entry); - if (GTK_IS_WINDOW (toplevel)) - { - gtk_window_set_transient_for (GTK_WINDOW (completion->priv->popup_window), - GTK_WINDOW (toplevel)); - gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)), - GTK_WINDOW (completion->priv->popup_window)); - } - - gtk_window_set_display (GTK_WINDOW (completion->priv->popup_window), - gtk_widget_get_display (completion->priv->entry)); gtk_widget_realize (completion->priv->popup_window); _gtk_entry_completion_resize_popup (completion); - if (completion->priv->device) - { - gtk_grab_add (completion->priv->popup_window); - gdk_seat_grab (gdk_device_get_seat (completion->priv->device), - gtk_widget_get_surface (completion->priv->popup_window), - GDK_SEAT_CAPABILITY_POINTER | GDK_SEAT_CAPABILITY_TOUCH, - TRUE, NULL, NULL, - prepare_popup_func, completion); - - completion->priv->has_grab = TRUE; - } + gtk_popover_popup (GTK_POPOVER (completion->priv->popup_window)); } void @@ -1547,14 +1467,7 @@ _gtk_entry_completion_popdown (GtkEntryCompletion *completion) if (!gtk_widget_get_mapped (completion->priv->popup_window)) return; - if (completion->priv->has_grab) - { - gdk_seat_ungrab (gdk_device_get_seat (completion->priv->device)); - gtk_grab_remove (completion->priv->popup_window); - completion->priv->has_grab = FALSE; - } - - gtk_widget_hide (completion->priv->popup_window); + gtk_popover_popdown (GTK_POPOVER (completion->priv->popup_window)); } static gboolean @@ -2036,8 +1949,7 @@ gtk_entry_completion_timeout (gpointer data) } else if (gtk_widget_get_visible (completion->priv->popup_window)) _gtk_entry_completion_popdown (completion); - - return FALSE; + return G_SOURCE_REMOVE; } static inline gboolean @@ -2428,6 +2340,15 @@ accept_completion_callback (GtkEntryCompletion *completion) return FALSE; } +static gboolean +text_focus_out (GtkEntryCompletion *completion) +{ + if (gtk_widget_get_mapped (completion->priv->popup_window)) + return FALSE; + + return accept_completion_callback (completion); +} + static void completion_insert_text_callback (GtkText *entry, const gchar *text, @@ -2461,7 +2382,7 @@ connect_completion_signals (GtkEntryCompletion *completion) controller = priv->entry_key_controller = gtk_event_controller_key_new (); g_signal_connect (controller, "key-pressed", G_CALLBACK (gtk_entry_completion_key_pressed), completion); - g_signal_connect_swapped (controller, "focus-out", G_CALLBACK (accept_completion_callback), completion); + g_signal_connect_swapped (controller, "focus-out", G_CALLBACK (text_focus_out), completion); gtk_widget_add_controller (GTK_WIDGET (text), controller); completion->priv->changed_id = @@ -2548,10 +2469,8 @@ _gtk_entry_completion_disconnect (GtkEntryCompletion *completion) unset_accessible_relation (completion->priv->popup_window, completion->priv->entry); - gtk_window_set_attached_to (GTK_WINDOW (completion->priv->popup_window), - NULL); - - gtk_window_set_transient_for (GTK_WINDOW (completion->priv->popup_window), NULL); + gtk_popover_set_relative_to (GTK_POPOVER (completion->priv->popup_window), + NULL); completion->priv->entry = NULL; } @@ -2564,7 +2483,7 @@ _gtk_entry_completion_connect (GtkEntryCompletion *completion, set_accessible_relation (completion->priv->popup_window, completion->priv->entry); - gtk_window_set_attached_to (GTK_WINDOW (completion->priv->popup_window), + gtk_popover_set_relative_to (GTK_POPOVER (completion->priv->popup_window), completion->priv->entry); connect_completion_signals (completion); -- 2.30.2